﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data.SqlClient;
using System.IO;

namespace WebService1
{
    
    /// <summary>
    /// service one
    /// </summary>
    [WebService(Namespace = "http://localhost/Portal/Service1.asmx")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    [System.Web.Script.Services.ScriptService]
    public class Service1 : System.Web.Services.WebService
    {


        string address = @"C:\Users\Ichijin\Documents\Meh\Users.txt";

        //string address = @"C:\Users\Stanley\Documents\projects\WebService1\WindowsFormsApplication1\bin\Debug\Users.txt";
        //string address = @"C:\Users\Ichijin\Documents\Meh\Users.txt";
       // string address = @"C:\inetpub\wwwroot\Portal\Users.txt";
        //string address = @"C:\Users\PhantomZero\Documents\Visual Studio 2010\Projects\Portal(1)\Portal\WindowsFormsApplication1\bin\Debug\Users.txt";

        

        #region Variables

        /// <summary>
        /// Random generator for the random invite.
        /// </summary>
        Random r = new Random();

        /// <summary>
        /// List of users (online and offline).
        /// </summary>
        static List<User> Users = new List<User>();

        /// <summary>
        /// list of pending Invites.
        /// </summary>
        static List<invite> Invites = new List<invite>();

        /// <summary>
        /// Chat message buffer array (in case multiple people (with a max of 5) send a message simultaneously).
        /// </summary>
        static string[] Message = new string[5];

        /// <summary>
        /// Index of the chat, so that people who log in don't see previously send messages (including their own login message).
        /// </summary>
        static int index = 0;

        /// <summary>
        /// The IP address of the game server, OFFLINE means it hasn't been send yet and will be handled correctly.
        /// </summary>
        static string SGameIp = "OFFLINE";

        #endregion
        #region WebMethods

        #region Login/Signup

        /// <summary>
        /// This method signs new users up, it also updates the database.
        /// </summary>
        [WebMethod]
        public int Signup(string name, string pass)
        {
            foreach (User user in Users)
            {
                if (name == user.userName)
                {
                    return 0;
                }
            }
            User u = new User(name, pass);
            Users.Add(u);
            FileStream FS = new FileStream(address, FileMode.OpenOrCreate, FileAccess.ReadWrite);

            StreamWriter Writer = new StreamWriter(FS);
            Writer.WriteLine("This line is a dummy line!");
            for (int i = 0; i < Users.Count; i++)
            {
                Writer.WriteLine(Users[i].userName + ";" + Users[i].password + ";" + Users[i].Won + ";" + Users[i].Lost + ";");
            }
            Writer.Close();
            FS.Close();
            return 1;
        }

        /// <summary>
        /// To log in.
        /// </summary>
        [WebMethod]
        public int Login(string name, string pass)
        {
            ReadDB();
            foreach (User u in Users)
            {
                if (name == u.userName && pass == u.password && u.online == false)
                {
                    Message[index % 5] = (" " + name + " has joined the chat.");
                    index = (index + 1) % 5;
                    u.online = true;
                    return 3;
                }
                else if (name == u.userName && pass == u.password && u.online == true)
                {
                    return 2;
                }
                else if (name == u.userName)
                {
                    return 1;
                }
            }
            return 0;
        }

        /// <summary>
        /// To log out.
        /// </summary>
        [WebMethod]
        public bool Logout(string name)
        {
            foreach (User u in Users)
            {
                if (name == u.userName)
                {
                    Message[index % 5] = (" " + name + " has logged out.");
                    index = (index + 1) % 5;
                    u.online = false;
                    return true;
                }
            }
            return false;
        }

        #endregion
        #region Chat

        /// <summary>
        /// This method gets the list of chatters that are online
        /// </summary>
        [WebMethod]
        public string[] GetOnChatters(string name)
        {
            int onCount = 0, next = 0;
            for (int i = 0; i < Users.Count; i++)
            {
                if (Users[i].online == true)
                {
                    onCount++;
                }
            }
            string[] strUser = new string[onCount - 1];
            for (int i = 0; i < Users.Count; i++)
            {
                if (Users[i].userName != name && Users[i].online == true)
                {
                    strUser[next] = Users[i].userName;
                    next++;
                }
            }
            return strUser;
        }

        /// <summary>
        /// This method gets a list of chatters that are offline.
        /// </summary>
        [WebMethod]
        public string[] GetOffChatters(string name)
        {
            int offCount = 0, next = 0;
            for (int i = 0; i < Users.Count; i++)
            {
                if (Users[i].online == false)
                {
                    offCount++;
                }
            }
            string[] strUser = new string[offCount];
            for (int i = 0; i < Users.Count; i++)
            {
                if (Users[i].userName != name && Users[i].online == false)
                {
                    strUser[next] = Users[i].userName;
                    next++;
                }
            }
            return strUser;
        }

        /// <summary>
        /// This is used to add messages to the buffer.
        /// </summary>
        [WebMethod]
        public void SendMessage(string name, string message)
        {
            Message[index % 5] = (" " + name + ": " + message);
            index = (index + 1) % 5;
        }

        /// <summary>
        /// this returns the index for the chat, so 
        /// a user who logs in doesn't get all previous messages.
        /// (only used after login)
        /// </summary>
        [WebMethod]
        public int Index()
        {
            return index;
        }

        /// <summary>
        /// This method receives all new messages.
        /// </summary>
        [WebMethod]
        public string[] ReceiveMessage(int begin)
        {
            if (Message[0] != null)
            {
                int temp = 0;
                string[] strMess = new string[((index + 5) - begin) % 5];
                if (begin > index)
                {
                    temp = 5;
                }
                for (int i = begin; i < (index + temp); i++)
                {
                    strMess[(i - begin) % 5] = Message[i];
                }
                return strMess;
            }
            return new string[0];
        }

        #endregion
        #region Invite and Info

        /// <summary>
        /// This method will receive an array of strings with the chosen user info.
        /// </summary>
        [WebMethod]
        public string[] GetUserInfo(string name)
        {
            foreach (User u in Users)
            {
                if (u.userName == name)
                {
                    return new string[3]{u.userName, u.Won.ToString(), u.Lost.ToString()};
                }
            }
            return new string[0];
        }

        /// <summary>
        /// This is the server based method to invite a person.
        /// (It will add a user to the list of invites(class))
        /// </summary>
        [WebMethod]
        public bool SendInvite(string inviter, string invitee, int Size)
        {
            foreach (User u in Users)
            {
                if (u.userName == invitee && u.inviting == false)
                {
                    invite inv = new invite();
                    inv.inviter = inviter;
                    inv.invitee = invitee;
                    inv.response = 0;
                    inv.type = Size;
                    Invites.Add(inv);
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// This method will send the response to the inviter from the invitee.
        /// </summary>
        [WebMethod]
        public void SendResponse(string invitee, bool response)
        {
            int temp = -1;
            for (int i = 0; i < Invites.Count; i++)
            {
                if (Invites[i].invitee == invitee)
                {
                    temp = i;
                    break;
                }
            }
            if (temp > -1)
            {
                if (response)
                {
                    Invites[temp].response = 1;
                }
                else
                {
                    Invites[temp].response = 2;
                }
            }
        }

        /// <summary>
        /// This method will check for invitations.
        /// </summary>
        [WebMethod]
        public string[] CheckInvitation(string name)
        {
            string[] Ret = new string[2];
            for (int i = 0; i < Invites.Count; i++)
            {
                if (Invites[i].invitee == name)
                {
                    Ret[0] = Invites[i].inviter;
                    Ret[1] = Convert.ToString(Invites[i].type);
                    return Ret;
                }
            }
            Ret[0] = "";
            Ret[1] = "";
            return Ret;
        }

        /// <summary>
        /// This method receives the response for the inviter and handles the serverside management of the invites list.
        /// </summary>
        [WebMethod]
        public int InvResponse(string inviter)
        {
            for (int i = 0; i < Invites.Count; i++)
            {
                if (inviter == Invites[i].inviter)
                {
                    if (Invites[i].response == 1)
                    {
                        Invites.Remove(Invites[i]);
                        return 1;
                    }
                    else if (Invites[i].response == 2)
                    {
                        Invites.Remove(Invites[i]);
                        return 2;
                    }
                }
            }
            return 0;
        }

        /// <summary>
        /// this method sets the correct ip address for the Game server.
        /// </summary>
        [WebMethod]
        public void GameIP(string ip)
        {
            SGameIp = ip;
        }

        /// <summary>
        /// This method sends the IP address.
        /// </summary>
        [WebMethod]
        public string GetGameIP()
        {
            return SGameIp;
        }

        #endregion

        #endregion
        #region Methods

        /// <summary>
        /// This method reads the database.
        /// </summary>
        private void ReadDB()
        {

            FileStream FS = new FileStream(address, FileMode.OpenOrCreate, FileAccess.ReadWrite);

            FS.Seek(0, SeekOrigin.Begin);
            StreamReader Reader = new StreamReader(FS);
            string Name = "", Pass = "", temp = "", numToInt = "";
            int win = 0, lose = 0;
            temp = Reader.ReadLine();
            char c = temp[0];
            bool endOfFile = true;
            while (endOfFile == true)
            {
                c = (char)Reader.Read();
                if (c != 65535)
                {
                    while (c != ';')
                    {
                        Name += c;
                        c = (char)Reader.Read();
                    }
                    c = (char)Reader.Read();
                    while (c != ';')
                    {
                        Pass += c;
                        c = (char)Reader.Read();
                    }
                    c = (char)Reader.Read();
                    numToInt = null;
                    while (c != ';')
                    {
                        numToInt += c;
                        c = (char)Reader.Read();
                    }
                    win = Convert.ToInt32(numToInt);
                    c = (char)Reader.Read();
                    numToInt = null;
                    while (c != ';')
                    {
                        numToInt += c;
                        c = (char)Reader.Read();
                    }
                    lose = Convert.ToInt32(numToInt);
                    bool sameUser = false;
                    foreach (User U in Users)
                    {
                        if (U.userName == Name)
                        {
                            sameUser = true;
                        }
                    }
                    if (sameUser == false)
                    {
                        User u = new User(Name, Pass, win, lose);
                        Users.Add(u);
                    }
                    Name = "";
                    Pass = "";
                    win = 0;
                    lose = 0;
                    c = (char)Reader.Read();
                    c = (char)Reader.Read();
                }
                else
                {
                    endOfFile = false;
                }
            }
            Reader.Close();
            FS.Close();
        }

        #endregion
    }
}